package com.yoso.core.util;


import cn.hutool.core.collection.CollUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * <p>
 *  占位符解析器
 * </p>
 *
 * @author Michael Xu
 * @version 1.0
 * @date 2023/4/3 18:23
 */
public class PlaceholderResolver {
    /**
     * 默认前缀占位符
     */
    private static final String DEFAULT_PLACEHOLDER_PREFIX = "${";

    /**
     * 默认后缀占位符
     */
    private static final String DEFAULT_PLACEHOLDER_SUFFIX = "}";

    /**
     * 默认单例解析器
     */
    private static PlaceholderResolver defaultResolver = new PlaceholderResolver();

    /**
     * 占位符前缀
     */
    private String placeholderPrefix = DEFAULT_PLACEHOLDER_PREFIX;

    /**
     * 占位符后缀
     */
    private String placeholderSuffix = DEFAULT_PLACEHOLDER_SUFFIX;

    private PlaceholderResolver() {
    }

    private PlaceholderResolver(String placeholderPrefix, String placeholderSuffix) {
        this.placeholderPrefix = placeholderPrefix;
        this.placeholderSuffix = placeholderSuffix;
    }

    /**
     * 获取默认的占位符解析器，即占位符前缀为"${", 后缀为"}"
     *
     * @return
     */
    public static PlaceholderResolver getDefaultResolver() {
        return defaultResolver;
    }

    public static PlaceholderResolver getResolver(String placeholderPrefix,
                                                  String placeholderSuffix) {
        return new PlaceholderResolver(placeholderPrefix, placeholderSuffix);
    }


    /**
     * 获取占位符变量
     *
     * @param text 文本
     * @return 变量集合
     */
    public List<String> resolveVariables(String text) {
        int start = text.indexOf(this.placeholderPrefix);
        if (start == -1) {
            return Collections.emptyList();
        }
        int end;
        List<String> params = new ArrayList<>();
        while (start != -1) {
            end = text.indexOf(this.placeholderSuffix, start);
            params.add(text.substring(start + this.placeholderPrefix.length(), end));
            start = text.indexOf(this.placeholderPrefix, end);
        }
        return params;
    }

    /**
     * 移除占位符 groovy使用
     *
     * @param text 文本
     * @return 移除占位符后的文本
     */
    public String removePlaceholder(String text) {
        int start = text.indexOf(this.placeholderPrefix);
        if (start == -1) {
            return text;
        }
        StringBuilder result = new StringBuilder(text);
        while (start != -1) {
            int end = result.indexOf(this.placeholderSuffix, start);
            // 获取属性
            String variable = result.substring(start + this.placeholderPrefix.length(),
                    end);
            result.replace(start, end + this.placeholderSuffix.length(), variable);
            start = result.indexOf(this.placeholderPrefix, start + variable.length());
        }
        return result.toString();
    }

    /**
     * 根据aviator工具类解析
     *
     * @param text      文本
     * @param variables variables
     * @return 替换后的文本 string
     */
    public String resolveAndReplace(String text, Map<String, Object> variables) {
        if (CollUtil.isEmpty(variables)) {
            return text;
        }
        int start = text.indexOf(this.placeholderPrefix);
        StringBuilder result = new StringBuilder(text);
        if (start != -1) {
            while (start != -1) {
                int end = result.indexOf(this.placeholderSuffix, start);
                // 获取占位符属性值，如${id}, 即获取id
                String placeholder = result.substring(start + this.placeholderPrefix.length(),
                        end).trim();
                // 替换整个占位符内容，即将${id}值替换为替换规则回调中的内容
                Object executeVal = variables.get(placeholder);
                String replaceContent = placeholder.trim().isEmpty() ? ""
                        : ((executeVal == null) ? "" : executeVal.toString());
                result.replace(start, end + this.placeholderSuffix.length(), replaceContent);
                start = result.indexOf(this.placeholderPrefix,
                        start + replaceContent.length());
            }
        }
        String resultValue = result.toString();
        return resultValue;
    }

}
